package com.zxj.geekstudy.util;

import lombok.SneakyThrows;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import javax.annotation.Resource;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    @Resource
    private RedisTemplate redisTemplate;

    public void set(final Object k, final Object v, final long exptime, TimeUnit timeUnit) {
        ValueOperations operations = redisTemplate.opsForValue();
        operations.set(k, v, exptime, timeUnit);
    }

    public Boolean lock(final Object k, final Object v, final long exptime, TimeUnit timeUnit) {
        ValueOperations operations = redisTemplate.opsForValue();
        return operations.setIfAbsent(k, v, exptime, timeUnit);
    }

    @SneakyThrows
    public Boolean unlock(final Object k, final Object v) {
        // 字符串方式
//        String script =
//                "if redis.call('get',KEYS[1]) == ARGV[1] then" +
//                        "   return redis.call('del',KEYS[1]) " +
//                        "else" +
//                        "   return 0 " +
//                        "end";
        // 默认DefaultRedisScript方式
//        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//        redisScript.setResultType(Long.class);
//        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/unlock.lua")));
//        Long result = (Long) redisTemplate.execute(redisScript, Collections.singletonList(k), v);
        // 显示读文件方式
        Path path = Paths.get(ResourceUtils.getURL("classpath:").toURI().resolve("lua/unlock.lua"));
        byte[] script = Files.readAllBytes(path);
        Long result = (Long) redisTemplate.execute(RedisScript.of(new String(script), Long.class), Collections.singletonList(k), v);
        return !Objects.equals(result, 0L);
    }

    @SneakyThrows
    public Boolean decrementGoods(final Object k) {
//        String script =
//                "if tonumber(redis.call('get',KEYS[1])) > 0 then" +
//                        "   redis.call('DECR',KEYS[1]) " +
//                        "   return 1 "  +
//                        "else" +
//                        "   return 0 " +
//                        "end";
        Path path = Paths.get(ResourceUtils.getURL("classpath:").toURI().resolve("lua/unlock.lua"));
        byte[] script = Files.readAllBytes(path);
        Long result = (Long) redisTemplate.execute(RedisScript.of(new String(script), Long.class), Collections.singletonList(k));
        return !Objects.equals(result, 0L);
    }

    public void publish(String channel, String message) {
        redisTemplate.convertAndSend(channel, message);
    }
}
